﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using ufida.u9.ait.openapi.utils;
using UFIDA.U9.Base;
using UFIDA.U9.CBO.HR.Department;
using UFIDA.U9.CBO.MFG.CostElement;
using UFIDA.U9.CBO.MFG.Enums;
using UFIDA.U9.CBO.SCM.Item;
using UFIDA.U9.CBO.SCM.ProjectTask;
using UFIDA.U9.CBO.SCM.Warehouse;
using UFIDA.U9.ISV.MO;
using UFIDA.U9.MO.Enums;
using UFIDA.U9.MO.MO;
using UFIDA.U9.SM.SO;
using UFSoft.UBF.Business;
using UFSoft.UBF.Business.Adapter;

namespace ufida.u9.ait.openapi
{
    internal class MOBase
    {
        /// <summary>
        /// 生产订单开工
        /// </summary>
        /// <param name="mo"></param>
        /// <returns></returns>
        public static MO StartDoc(MO mo)
        {
            U9Utils.ClearCache();
            mo = mo.Key.GetEntity();

            //调用产业链服务
            StartMo sv=new StartMo();
            sv.MOOperateParamDTOs = new List<MOOperateParamDTO>()
            {
                new MOOperateParamDTO()
                {
                    MODocNo=mo.DocNo,//开工单号
                    LineNum=10,//开工行号
                    OperateQty=mo.ProductQty,//开工数量
                    OperateType=true,//true-开工 false-反开工
                }
            };
            List<MOOperateParamDTO> mOOperateParamDTOs = sv.Do();
            //校验返回值
            foreach(var item in mOOperateParamDTOs)
            {
                if (item.OperateResult == false)
                {
                    throw new Exception($"单号:[{mo.DocNo}],开工错误:{item.ErrorMsg}");
                }
            }
            return mo;
        }

        public static MO ApproveDoc(MO mo)
        {
            mo = mo.Key.GetEntity();

            if (mo.DocState != MOStateEnum.Opened && mo.DocState != MOStateEnum.Approving)
                throw new Exception($"单号：[{mo.DocNo}]状态不为开立或提交，不能审核！");

            using (ISession session = Session.Open())
            {
                mo.DocState = MOStateEnum.Approved;
                mo.ApproveBy = Context.LoginUser;
                mo.ApproveOn = DateTime.Now;
                mo.WFCurrentState = 2;
                mo.IsCounteractPP = true;//生产计划抵消标志
                mo.CancelApproveBy = "";
                mo.CancelApproveOn = DateTime.MinValue;
                mo.BusinessCreatedOn = DateTime.Now;//业务制单日期
                //mo.ActualStartDate = DateTime.Now;//业务开始时间 改在create时赋值

                session.Commit();
            }

            return mo;
        }
        private static MO CreateHead(MOAITDTOData dto)
        {
            MO mo = MO.Create();
            MODefault(dto, mo);
            MOQty(dto, mo);
            //来源单据
            if (dto.MOSourceDocType < 0)
                mo.MOSourceDocType = MOSourceDocTypeEnum.GetFromValue(3);//来源单据类型=手工
            else
            {
                if (dto.SrcDoc == null || string.IsNullOrEmpty(dto.SrcDoc.SrcDocNo))
                    throw new Exception("来源单据传入为空");

                mo.MOSourceDocType = MOSourceDocTypeEnum.GetFromValue(dto.MOSourceDocType);
                if (dto.MOSourceDocType == 1)
                {
                    //来源单据类型=销售订单
                    FromSO(dto, mo);
                }
            }
            //MO产出表
            UpdateMOOutput(mo, dto);

            return mo;
        }

        private static void MODefault(MOAITDTOData dto, MO mo)
        {
            mo.DocNo = dto.DocNo;
            if (String.IsNullOrEmpty(dto.BusinessDate))
                throw new Exception("BusinessDate必填");
            mo.BusinessDate = DateTime.Parse(dto.BusinessDate);
            if (!string.IsNullOrEmpty(dto.StartDate))
            {
                mo.StartDate = DateTime.Parse(dto.StartDate);//计划开工日期
            }
            else
            {
                mo.StartDate = mo.BusinessDate;
            }
            if (!String.IsNullOrEmpty(dto.CompleteDate))
            {
                mo.CompleteDate = DateTime.Parse(dto.CompleteDate);//计划完工日期
            }
            else
            {
                mo.CompleteDate = mo.BusinessDate;
            }
            if (!string.IsNullOrEmpty(dto.ActualStartDate))
            {
                mo.ActualStartDate = DateTime.Parse(dto.ActualStartDate);//业务开始时间
            }
            else
            {
                mo.ActualStartDate = mo.BusinessDate;//业务开始时间
            }

            if (dto.MODocType == null) throw new Exception("MODocType必填");
            mo.MODocType = EntityUtils.GetEntityByCode<MODocType>(dto.MODocType.Code);
            //组织
            mo.Org = Context.LoginOrg;
            mo.OwnerOrg = mo.Org;
            mo.CompleteInOrg = mo.Org;
            //料品
            if (dto.ItemMaster == null) throw new Exception("ItemMaster必填");
            ItemMaster item = EntityUtils.GetEntityByCode<ItemMaster>(dto.ItemMaster.Code);
            mo.ItemMaster = item;

            // 存储地点
            if (item.InventoryInfo.Warehouse != null)
            {
                mo.CompleteWh = item.InventoryInfo.Warehouse;
                mo.SCVWh = item.InventoryInfo.Warehouse;
            }
            if (dto.CompleteWh != null)
            {
                mo.CompleteWh = EntityUtils.GetEntityByCode<Warehouse>(dto.CompleteWh.Code);
                mo.SCVWh = mo.CompleteWh;
            }
            if (item.InventoryInfo.Bin != null)
            {
                mo.CompleteBin = item.InventoryInfo.Bin;
                mo.SCVBin = item.InventoryInfo.Bin;
            }

            //BOM母项
            if (dto.BOMMaster != null)
            {
                UFIDA.U9.CBO.MFG.BOM.BOMMaster bom = EntityUtils.GetBOM(dto.BOMMaster.Code, mo.BusinessDate);
                mo.BOMMaster = bom;
                mo.BOMVersion = bom.BOMVersion;
                mo.BOMEffeDate = bom.EffectiveDate;
                mo.BOMAlternate = bom.AlternateType;
            }

            //扩展字段处理
            if (dto.DescFlexField != null)
            {
                mo.DescFlexField = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                DTOUtils.DTOPropCopy(dto.DescFlexField, mo.DescFlexField);
            }
            //备注
            if (!string.IsNullOrEmpty(dto.MOMemos))
            {
                MOMemo memo = null;
                if (mo.MOMemos != null && mo.MOMemos.Count > 0)
                {
                    memo = mo.MOMemos[0];
                }
                else
                {
                    memo = MOMemo.Create(mo);
                    memo.MemoSeq = 10;
                }
                memo.Description = dto.MOMemos;
            }

            //其它
            mo.IsMRPorMPS = true;
            mo.BusinessType = UFIDA.U9.Base.Doc.BusinessTypeEnum.GetFromValue(47);//业务类型
            mo.ZoomRate = 1;
            mo.Project = EntityUtils.GetEntityByCode<Project>(dto.Project);//项目
            mo.Department = EntityUtils.GetEntityByCode<Department>(dto.Department);//部门
            mo.Priority = 99;
            mo.IsStartQtyPicking = true;
        }

        private static void MOQty(MOAITDTOData dto, MO mo)
        {
            ItemMaster item = mo.ItemMaster;
            //计量单位
            mo.RcvUOM = item.InventorySecondUOM;
            mo.StoreBaseUOM = item.InventorySecondUOM.BaseUOM;
            mo.ProductUOM = item.ManufactureUOM;
            mo.ProductBaseUOM = item.ManufactureUOM.BaseUOM;
            mo.CostUOM = item.CostUOM;
            mo.CostBaseUOM = item.CostUOM.BaseUOM;

            //数量
            mo.ProductQty = dto.ProductQty;
            mo.MRPQty = dto.ProductQty;
            mo.ProductQtybyStoreUOM = dto.ProductQty * U9Utils.GetUom2Rate(mo.ProductUOM, mo.RcvUOM, item);
            //生产数量(成本)
            if (dto.ProductQtybyCostUOM > 0)
            {
                mo.ProductQtybyCostUOM = dto.ProductQtybyCostUOM;
            }
            else
            {
                mo.ProductQtybyCostUOM = dto.ProductQty * U9Utils.GetUom2Rate(mo.ProductUOM, mo.CostUOM, item);
            }

            //转换率
            mo.PBUToSBURate = mo.ProductQtybyStoreUOM / mo.ProductQty;//生产-库存
            mo.PBUToCBURate = mo.ProductQtybyCostUOM / mo.ProductQty;//生产-成本
            mo.PUToPBURate = 1;
            mo.SUToSBURate = 1;
            mo.CUToCBURate = 1;
            mo.UOMRateMfgToRcv = 1;

        }

        /// <summary>
        /// FromSO
        /// </summary>
        /// <param name="dto"></param>
        /// <param name="mo"></param>
        /// <exception cref="Exception"></exception>
        private static void FromSO(MOAITDTOData dto, MO mo)
        {
            string path = $"DocSubLineNo=10 and SOLine.DocLineNo={dto.SrcDoc.SrcDocLineNo} and SOLine.SO.DocNo='{dto.SrcDoc.SrcDocNo}'";
            SOShipline shipline = SOShipline.Finder.Find(path);
            if (shipline == null) throw new Exception($"查询销售订单失败,path:[{path}]");
            if (shipline.ItemInfo.ItemCode != mo.ItemMaster.Code)
                throw new Exception($"来源料品[{shipline.ItemInfo.ItemCode}]与传入料品[{mo.ItemMaster.Code}]不同");
            SOLine soline = shipline.SOLine;
            SO so = soline.SO;
            mo.SrcDoc = new UFIDA.U9.MO.PropertyTypes.MOSourceDoc()
            {
                SrcDocSublineNo = shipline.DocSubLineNo.ToString(),
                SrcDocSubline = shipline,
                SrcDocOrg = shipline.Org,
                SrcDocNo = so.DocNo,
                SrcDocLineNo = soline.DocLineNo.ToString(),
                SrcDocLine = soline,
                SrcDoc = so,
            };

            MOSourceDocRelation srcRel = MOSourceDocRelation.Create(mo);
            srcRel.SrcDoc = mo.SrcDoc;

            srcRel.TUToTBURate = 1;
            srcRel.TBUToPBURate = 1;
            srcRel.PUToPBURate = 1;
            srcRel.SrcType = mo.MOSourceDocType;
            srcRel.SrcOperator = so.Seller;
            srcRel.SrcDepartment = so.SaleDepartment;
            srcRel.SrcCustomer = so.OrderBy.Customer;
            //数量单位
            srcRel.RequireQty4TUOM = soline.OrderByQtyTU;
            srcRel.RequireQty4PUOM = soline.OrderByQtyPU;
            srcRel.SrcDocAssignQty = dto.ProductQty;
            srcRel.MoAssignQty = dto.ProductQty;
            srcRel.SrcUOM = mo.ProductUOM;
            srcRel.ProductUOM = mo.ProductUOM;
        }

        private static void UpdateMOOutput(MO mo, MOAITDTOData dto)
        {
            MOOutput output = null;
            if (mo.MOOutputs == null || mo.MOOutputs.Count <= 0)
            {
                output = MOOutput.Create(mo);
            }
            else
            {
                output = mo.MOOutputs[0];
            }
            output.Item = mo.ItemMaster;
            output.PlanOutputQty = mo.ProductQty;
            output.BOMOutputQty = mo.ProductQty;
            //单位
            output.RcvUOM = mo.RcvUOM;
            output.StoreBaseUOM = mo.StoreBaseUOM;
            output.ProductUOM = mo.ProductUOM;
            output.ProductBaseUOM = mo.ProductBaseUOM;
            output.OutputUOM = mo.ProductUOM;
            output.CostUOM = mo.CostUOM;
            output.CostBaseUOM = mo.CostBaseUOM;
            //转换率
            output.SUToSBURate = mo.SUToSBURate;
            output.PUToPBURate = mo.PUToPBURate;
            output.PBUToSBURate = mo.PBUToSBURate;
            output.PBUToCBURate = mo.PBUToCBURate;
            output.CUToCBURate = mo.CUToCBURate;
            //其它
            output.BOMOutputRatio = 1;
            output.BOMCostRatio = 1;
        }

        public static MO CreateDoc(MOAITDTOData dto)
        {
            MO mo = null;
            using (ISession session = Session.Open())
            {
                mo = CreateHead(dto);
                CreatePick(mo, dto);
                session.Commit();
            }
            return mo;
        }

        private static MO CreatePick(MO mo, MOAITDTOData dto)
        {
            if (dto.PickList == null || dto.PickList.Count <= 0)
                return mo;
            foreach (var pick in dto.PickList)
            {
                CreatePick(mo, pick);
            }
            return mo;
        }

        public static void ModifyPick(MOPickList pick, MOPickListAITDTOData dto1)
        {
            MO mo = pick.MO;
            if (pick.ItemMaster.Code != dto1.ItemMaster.ItemCode)
                throw new Exception($"备料料号[{pick.ItemMaster.Code}]与传入料号[{dto1.ItemMaster.ItemCode}]不同,不能变更");
            pick.ActualReqQty = dto1.ActualReqQty;//实际用量
            pick.STDReqQty= dto1.ActualReqQty;//标准用量
            pick.QPA = pick.STDReqQty / mo.ProductQty;//每装配件数量=标准用量/生产数量
            if (!string.IsNullOrEmpty(dto1.ActualReqDate))
                pick.ActualReqDate = DateTime.Parse(dto1.ActualReqDate);//实际需求日期
            pick.Remark = dto1.Remark;//备注
            //扩展字段
            if (dto1.DescFlexField != null)
            {
                if (pick.DescFlexField == null) pick.DescFlexField = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                DTOUtils.DTOPropCopy(dto1.DescFlexField, pick.DescFlexField);
            }
        }

        public static void CreatePick(MO mo, MOPickListAITDTOData dto1)
        {
            //创建备料实体
            MOPickList pick = MOPickList.Create(mo);
            if (dto1.DocLineNO > 0)
            {
                pick.DocLineNO = dto1.DocLineNO;
            }
            else
            {
                pick.DocLineNO = mo.MOPickLists.Count * 10;
            }
            //组织
            pick.SupplyOrg = mo.Org;
            //料品
            ItemMaster item = EntityUtils.GetEntityByCode<ItemMaster>(dto1.ItemMaster.ItemCode);
            pick.ItemMaster = item;
            //单位
            pick.RcvUOM = item.InventoryUOM;
            pick.StoreBaseUOM = item.InventoryUOM.BaseUOM;
            pick.IssueUOM = item.MaterialOutUOM;
            pick.IssueBaseUOM = item.MaterialOutUOM.BaseUOM;
            pick.CostUOM = item.CostUOM;
            pick.CostBaseUOM = item.CostUOM.BaseUOM;
            //数量
            pick.ActualReqQty = dto1.ActualReqQty;//实际用量
            pick.STDReqQty = dto1.ActualReqQty;//标准用量
            pick.QPA = pick.STDReqQty/mo.ProductQty;//每装配件数量=标准用量/生产数量
            //转换率
            pick.IBUToCBURate = U9Utils.GetUom2Rate(pick.IssueUOM, pick.CostUOM, item);//发料-成本
            pick.SUToSBURate = 1;
            pick.IUToIBURate = 1;
            pick.IBUToSBURate = 1;
            pick.CUToCBURate = 1;

            //扩展字段处理
            if (dto1.DescFlexField != null)
            {
                pick.DescFlexField = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                DTOUtils.DTOPropCopy(dto1.DescFlexField, pick.DescFlexField);
            }

            //其它
            pick.Remark = dto1.Remark;//备注
            CostElement costElement = CostElement.Finder.FindByID(item.MfgInfo.CostElement);
            pick.CostElement = costElement;//成本要素
            pick.ConsignProcessItemSrc = ConsignProcessItemSrcEnum.GetFromValue(2);//委托料品来源
            if (string.IsNullOrEmpty(dto1.ActualReqDate))
                throw new Exception("ActualReqDate 为空");
            pick.ActualReqDate = DateTime.Parse(dto1.ActualReqDate);//实际需求日期
            pick.IsCalcCost = true;
            if (dto1.IssueStyle > -1)
            {
                pick.IssueStyle = IssueStyleEnum.GetFromValue(dto1.IssueStyle);//发料方式
            }
            else
            {
                pick.IssueStyle = IssueStyleEnum.Push;
            }
            pick.IsOverIssue = dto1.IsOverIssue;//超额发料
            if (dto1.MaterialType > -1)
            {
                pick.MaterialType = IsSueOverTypeEnum.GetFromValue(dto1.MaterialType);//超额类型
            }
            pick.StandardMaterialScale= dto1.StandardMaterialScale;//超额比例
            pick.FixedMaterialNum= dto1.FixedMaterialNum;//固定超额梁
            pick.JIT= dto1.JIT;//特定存储地点
            pick.SupplyWh=EntityUtils.GetEntityByCode<Warehouse>(dto1.SupplyWh);//供应地点
            pick.MOStartSetCheck= dto1.MOStartSetCheck;//订单开工检查
            pick.MOCompleteSetCheck= dto1.MOCompleteSetCheck;//订单完工检查
            pick.OPStartSetCheck= dto1.OPStartSetCheck;//工序开工检查
            pick.OPCompleteSetCheck= dto1.OPCompleteSetCheck;//工序完工检查
            pick.IsCoupleIssue= dto1.IsCoupleIssue;//齐套发料
            pick.IsDiffentBatchCtl= dto1.IsDiffentBatchCtl;//混批控制
            pick.Project=EntityUtils.GetEntityByCode<Project>(dto1.Project);//项目

            pick.OperationNum = "10";
            
            pick.ReplaceRatio = 1;
            pick.QtyType = UFIDA.U9.CBO.Enums.UsageQuantityTypeEnum.GetFromValue(1);//数量类型
            
            pick.PlanReqDate = mo.BusinessDate;
            pick.IsIssueOrgFixed = true;
            //pick.IsCheckUTE = true;
            pick.IsCalcCost = true;
            pick.IsAutoCreate = false;

        }
    }
}
